{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "## 第3章 k近邻法-习题\n",
    "\n",
    "### 习题3.1\n",
    "&emsp;&emsp;参照图3.1，在二维空间中给出实例点，画出$k$为1和2时的$k$近邻法构成的空间划分，并对其进行比较，体会$k$值选择与模型复杂度及预测准确率的关系。\n",
    "\n",
    "**解答：**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "%matplotlib inline\n",
    "import numpy as np\n",
    "from sklearn.neighbors import KNeighborsClassifier\n",
    "import matplotlib.pyplot as plt\n",
    "from matplotlib.colors import ListedColormap \n",
    "\n",
    "data = np.array([[5, 12, 1],\n",
    "                [6, 21, 0],\n",
    "                [14, 5, 0],\n",
    "                [16, 10, 0],\n",
    "                [13, 19, 0],\n",
    "                [13, 32, 1],\n",
    "                [17, 27, 1],\n",
    "                [18, 24, 1],\n",
    "                [20, 20, 0],\n",
    "                [23, 14, 1],\n",
    "                [23, 25, 1],\n",
    "                [23, 31, 1],\n",
    "                [26, 8, 0],\n",
    "                [30, 17, 1],\n",
    "                [30, 26, 1],\n",
    "                [34, 8, 0],\n",
    "                [34, 19, 1],\n",
    "                [37, 28, 1]])\n",
    "X_train = data[:, 0:2]\n",
    "y_train = data[:, 2]\n",
    "\n",
    "models = (KNeighborsClassifier(n_neighbors=1, n_jobs=-1),\n",
    "          KNeighborsClassifier(n_neighbors=2, n_jobs=-1))\n",
    "models = (clf.fit(X_train, y_train) for clf in models)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAA2cAAAE/CAYAAADCCbvWAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy86wFpkAAAACXBIWXMAAAsTAAALEwEAmpwYAABdUklEQVR4nO39e3Rbd37f/b5/IEiCJEiCulISJcOyZF18GdiWbdmWPZjxZOJkcu14pp1p00GbxnnO05wT9ulZq27+CaY9bfU8J0mRdZon6aTJwuTitLOcTO6dZJrMtke26bFsw7ZsU5YsbVOUBEmUBFIQCZEgfucPXMSbJJIiuQHw81qLS8AGCHy3IOG3v7/L92estYiIiIiIiIi3fF4HICIiIiIiIkrOREREREREqoKSMxERERERkSqg5ExERERERKQKKDkTERERERGpAkrOREREREREqoCSM6k6xpisMWb7PJ9rjTE7bvBYzBhzaGmjWzrGmH9sjPnbmzweNcYMLuD1HGPMv1ia6ERERKZT+1x5XO2zLBslZ3JLxhjXGPO5Kff/kTHmsjHm03M8N1r6Qv6NGccPGWNi83k/a23QWnvitgOvctbaP7TWfr58/2YN2UoxxnzZGPOqMWbUGON4GYuIiNyc2uflUaXt868YY44ZY64YY/qNMf/Uy3hk+Sg5kwUxxnwN+A3gC9bal27wtKvAPzXGhFcssGVmjPF7HcMKuQQkgIMexyEiIgug9rnuXQV+HOgEvgb8ujHmcW9DkuWg5EzmzRjzHPCrwA9ba1+9yVMzQBL45Zu81j83xnxY6uH7G2PMHVMeq/RQGWPWGmP+whgzYox5wxjz/5ljKsTnSr1Jl40xv2GMMdPfyvz/jDHDpZ6mp6c8sNkY8+fGmEvGmOPGmJ+b8ljcGPOiMeYPjDEjQMwY84gx5nAplnPGmF+7wbm9ZIz5Yun2gdL5/Gjp/ueMManS7cq0DmPMy6Vff6c0beQfTnm9f22MOW+MOWuM+Wc3+judEcMmY8y7xpj/93yeX2at/V/W2m8BZxbyeyIi4h21z6uiff5la22/tbZgrX0d+D7w2EJeQ2qDkjOZr/8H8O+Bp621h+fx/P8AfNEYs2vmA8aYnwJ+CfgHwHqKXzB/dIPX+Q2KvUXdFHuKvjbHc34MeBj4FPBl4IenPPYocAJYR7Ex+hNjzJrSY38EDAKbgWeB/zi1cQB+EngRCAF/CPw68OvW2g7gLuBbN4j5JSBauv1U6f0/PeX+rB5Na+1TpZufKk0b+R+l+90Ue8m2AD8L/IYxpusG7wuAKfaIvgT8F2vtr5SO/d/GmMwNft692euJiEhVU/u8ytpnY0wLxb/X92/2flKblJzJfP0Q0Ae8N58nW2vTwG8B/26Oh38e+E/W2g+ttXngPwKRqb1zAMaYBuCLwC9ba0ettR8A35zj9Q5aazPW2gHge0BkymPngYS1dqL0hXoU+IIxZitwAPg31tqctTYF/DfgZ6b87mvW2j8t9VKNARPADmPMOmtt1lrbd4PTf4npX/b/acr9TzPHl/9NTAD/rhT/XwNZYFaDOsVewKH4d/aN8kFr7f9urQ3d4Of+BcQjIiLVRe3z6muffwt4B/ibBcQrNULJmczX/wbcDfy3GdMSbub/BH7YGPOpGcfvoDhXOmOMyVBc52Qo9j5NtR7wA6emHDvFbOkpt0eB4JT7p621dsr9Tyj2xG0GLllrr8x4bGoMM9/rZyn+HfSXpnD82ByxALwG3G2M2UixIfo9YKsxZh3wCPDyDX5vLhdLDWTZzPOb6R8Dpyn2KIqISP1T+7yK2mdjzP8XuBf48oy/P6kTSs5kvs4DTwNPAv/3fH7BWnuRYnGJfz/joVPAz8/oHWqZY578BSAP9Ew5tnWBcW+Z0Vhto7ie6gywxhjTPuOx01NPYcb5HLPWfgXYQLFhe9EY0zbzDa21o8CbwC8CR6y148CrwP8BfGytHVrgOSxEHBgCXij1bAJgjPmt0lz5uX40LUJEpHapfV4l7bMx5uvAjwCft9aOLGOs4iElZzJv1tozwGeBZ4wx/3mev/ZrwOPAninHfgv4t8aYewCMMZ3GmC/N8X6TwJ8AcWNMqzFmN7DQ0rEbgP+XMaax9B57gL+21p6i+IX8n4wxAWPM/RR73v7wRi9kjPknxpj11toCxUXVAJM3ePpLwC9wfYqEM+P+XM4B89o/5iYmgC8BbcDvG2N8ANba/600V36un3vKv2yMaTDGBCj2iPpKfzeNtxmTiIgsI7XPq6J9/rfAV4EfKiXXUqeUnMmClL40Pws8a4z5T/N4/gjwfwFrphz7NsWerf9uipWWjlDsCZrLL1BccJsGfp/iIuFrCwj5dWAnxd6q/wA8O+VL7StAmGIv3bcpzgP/7k1e6xngfWNMluLi439krc3d4LkvAe1cnyIx8/5c4sA3S9NJvnyL87qhUk/gP6DY8P1uuQGYp58BxoDfpNgLOwb89mJjERGRlaH2ue7b5/9IcQTx2JSRtV9abCxSvYymq0otMcb8n0C3tXauqlAiIiLiAbXPIktDI2dS1Ywxu40x95uiRyhObfi213GJiIisZmqfRZbHatlVXWpXO8WpEpspLnr+VeDPPI1IRERE1D6LLANNaxQREREREakCmtYoIiIiIiJSBZSciYiIiIiIVIEVXXPW2tlqQ92hlXxLEZFV6+xHZ4esteu9jkOq37rWVhsOhVbmzS5eJLVmHBoa2NC2YWXeU0SkitysfV7R5CzUHeK5//rcSr6liMiq9fXPfP0Tr2OQ2hAOhTj83Aq2z8kk4WcHyawbpXd/78q9r4hIFbhZ+6xpjSIiIrKyYjHcF3sgd6N9gkVEViclZ3XIWsvwuWEG3hvg9IenGR8b9zokERGROTmu43UIK2rsyhin3j/FwHsDZC9lvQ5HRKqM9jmrM/nxPG9+903ODp3FrrWYvMH3qo/I/gjb7tnmdXgiIiJF4TCh7CAptw+AaDjqbTzLzFrLsTeO8eF7H2LXWzDAYbgzfCf3PXUfvgb1l4uIkrO688ErH3Bm4gyhp0IYYwDIj+Z56wdv0d7VTtfmLo8jFBERAaJRXAeiu/tIUf8J2tmPznLkoyN0PtlJQ1MDAHbS8vHhj2lLtbHjoR0eRygi1UDdNHVkfGwc94RL5z2dlcQMwN/qpyHcwIkjJzyMTkREZIZoFOc73YQIeB3Jsjv23jFa7m6pJGYApsHQfk87x44cwxash9GJSLVQclZHctkcBMDXOPtjbV7TzPDlYQ+iEhERuYVcDjfjeh3FshrJjNC8pnnW8cZgI+P5cSauTXgQlYhUGyVndaS5rRmbsxTyhVmPjQ+PE+wIehCViIjITcRihDOQGRokmUp6Hc2yaWtvY3x4doGu/Ggev8+Pv0krTUREyVldaW5tpmdrDyMfjWDt9ekRk+OTTJycYPs92z2MTkREZG5O9/P0HgmSyaTrtnrjznt3MvrRKHbyevtsC5aR/hHu2n2XCoKICKCCIHXnvifv4+pfXeVi30V863zYCQvn4N5772Xt1rVehyciIjKneCpEMpLxOoxl07Onh0vnL3Hy0EnYCMZnsOcsW9ZsYee+nV6HJyJVQslZnWlqaeLATx/g4qmLXDx7kcamRrof66atq83r0ERERG4umyWVTtVl1UbjM9wfvZ/whTDn3fNYa1l3zzq6NndNK+IlIqubxtDrkK/Bx/rwenY/tpu7HrpLiVkVKkwWKEzOXhsoIrJqxWLEjgdhZIREX8LraJaFMYbODZ3sfGQndz96N2u2rFFiVmVswap9Fk9p5ExkBY1cGOHo4aOcOXUGgM3bNrN7327a17V7HJmIiPfikV7iySShWHHtWT2OoEl1Gh8b56M3PsL9yCU/madrbRe7H9zNxu0bvQ5NVhmNnImskJELI7z8ly+TbknT/tl22j/bTjqQ5uW/eJkrF694HZ6ISNVYDfueSfXIj+d55c9f4fiV47Q82ULn5zsZ3TbKqy+9ymD/oNfhySqj5ExkhRx98yj2Tkt7uB2f34fP76M93E4hXOCjNz/yOjwRkeqRzZJy++q2cqNUl9NHT5NpzBC6J0RDcwPGGFo2tND2UBvvvf6epjnKilJyJrICCpMFzgycoa1n9vq/tq1tDJ4cnLb9gYjIqhWL4b7YQyibV4ImK2Lw5CCBntmjtU0dTYw3jjNyYcSDqGS1UnImsgK04FtEZAHKCZqmN4rX1G8qK0zJmcgKMD7Dlm1buHrq6qzHsgNZeu7sUQInIjJTLud1BLIKbL1zK7lTs/+tjQ+P0zzZTMf6Dg+iktVKyZnICtn18C58ro+REyMU8gUK+QIjJ0Zo+KSBXft2eR2eiEh1CYcJZyB1/BDJVNLraKSObd61ma7JLjLvZciP5bEFy2h6lKtvXeX+R+/H16DLZVk5+tcmskLa17bz6Z/8NFvyW8j+fZbs32fpmezh0z/5aYJrgl6HJyJSXaJRnP79RIb8ZIYGlaDJsvE3+Xn8xx9n15pdXHvtGsPfHabjbAdPPv0km3dt9jo8WWW0z5nICgquCfLQ5x/iQfsgoLVoIiI3FY3iECWeSpC4t5igxSIxr6OSOtTU0sSeJ/aw+/HdYIvLEUS8oJEzEQ8YY5SYiYjMUzzSS++RoEbQZNkZY5SYiadumZwZYwLGmB8YY94xxrxvjPl66fgaY8x3jTHHSn92LX+4IiIiAquvfY5nIkSymgIuIvVtPiNn14DPWms/BUSAZ4wx+4Hngb+z1u4E/q50X0RERFbG6mufczkyuYzXUYiILJtbJme2KFu621j6scBPAt8sHf8m8FPLEaCIiIjMtura52gU5zvdMDJCoi/hdTQiIstiXmvOjDENxpgUcB74rrX2dWCjtfYsQOnPDTf43eeMMYeNMYfPXzhPMpXUfHEREZElsFTt84XR0RWL+bbEYmRe2EYok9O1hIjUpXklZ9baSWttBOgBHjHG3DvfN7DWfsNau89au6+lEcJuRgt6RURElsBStc/rW1uXLcYlFw4TzgW8jkJEZFksqFqjtTYDOMAzwDljzCaA0p/nb/X7u0ZbcFKRaRWXNJImIiJye263fa45uRyZTBrHdbyORERkSc2nWuN6Y0yodLsF+BzQD/w58LXS074G/Nkt3629HaLRSknccH+acH+azPkBzR8XERFZgCVtn2tJaXPqUDZPyu1TgiYidWU+m1BvAr5pjGmgmMx9y1r7l8aY14BvGWN+FhgAvrSQN45Heq/fTiVI7C0u8O3d33vD3xEREZGKZWmfa0I0iutANJLCzbheRyMismRumZxZa98FHpjj+EXg6aUIIh7pJZ5MEvrqgBI0ERGReViJ9llERFbWfEbOVkYsRiaZJPzsIAnnIASKi30j3RGi4ai3sYmIiEj1yeUqa9hjkZjX0YiI3LYFFQRZdrEY7os99KYC9PZBaCir+eQiIiIyWzSK0/08kSG/qkCLSN2onpGzsliMeOlm3HEI7ztEyu0D0AiaiIiITOP07y+uPVvndSQiIrevukbOZopGcQ8fIJKG1PFDGkETERGR2XI5ryMQEVkS1Z2cQaVkbmTIT+r4IRLOQRLOQU1fEBEREYhGiaYD2pZHROpC9SdnUJlXnvmDHjLJbnpTxS9hJWgiIiISj/TS+0EHjIzo2kBEalptJGdlsVhxTVrpS1i9ZCIiIgLFBC1yqcnrMEREbkttJWdTTO0lS/QlcFxHa9JERERWuUwu43UIIiKLVrPJGRQTtMwL2wgNZXH7+4pr0jSSJiIisio53+kmNJQt7pcqIlKDqq+U/kLFYriOU7ztupVNrEOhbsKhMKAS/CJSP0YujHCq/xRXRq7Q2dXJtj3baOtq8zoskeoQi+Emk5VrgUh4v64BRGRF5LI5BvsHuXj+IoGWAFvv3krX5i6MMQt6ndpPzgCi0cpNN5kk+kwaMhncQB+ZQOkp+nIWkRo38P4Ab/3gLXw9Pvxr/ZzLnOPYt4/xaPRRNm7f6HV4ItWh1GmrfVJFZKUMnxvm0F8fIr8hT+PaRvKjeU7+r5Psvns3u/bvWlCCVh/J2VSxGE55JA2I7u4jlT9UvK0vZxGpUWMjY7z9+tsE9wfxt5a+urthfNM4bzhv8EzPM/ib6u8rXWRRolFcp3QNEEip/ReRZWMLlsN/dxizx9DZ3Vk5XthaoP/VfjbesZGuzV3zfr2aXnN2Q9Fo5WfqHmkqrysitersx2exG+z1xKykqbOJfGeeC+4FjyITqVKl/c9ERJbT8PlhrtgrtHa3Tjvua/Th2+pj4OjAgl6vPpOzqaYkaJmhQZKpZOVHRKRWXBu7hq/lBl/ZAZi4NrGyAYnUimxWbb6ILJuJ3AQmMPe0RX+rn9xYbkGvV//JGVQ2se49EiTcnybcn9Ym1iJSU7o2dFG4VJh13FoLl6B9bbsHUYlUt3ikd1rnrIjIUguuDWIzlkJ+dhs9fmGctRvXLuj1VkdyVhKP9OJ0P19M1LSJtYjUkPXh9bRPtHPlxJViQkZxnvvI0RHWta0jtCnkbYAiVarcOav9z0RkObS0txAOhxk+MlxJ0Ky1jKZHabrYRM+ungW93qpKzqaauYm1iEg1a/A38NgXHiOUCTH88jDDbw4z/NIwG/MbefiZhxdcqldERESWxn1P3ced7Xcy8tIII2+OMPLKCM0nm3niR58gEFzY2tdVXdorHuklnkwS+ur0EbTe/b2exSQiciOtna0c+OkDZC9myWVztHa2ao8zkfkqdcaqjReRpdbQ2EDk6Qi7ruwieylLY3MjnRs7F9VxumpHzipiMTIvbKO3D3r7IDSUJeEcxHEdryOre4XJApl0hkunL5Efz3sdjkhNMMbQvq6d9eH1SsxE5kmzZRbGWsuVoStcHLzItavXvA5HpGa0tLew/o71hLpDi57RsqpHzipiMeKlm/FkkvCzg9q4cpmlP06TeiXFtYZr0AD+MT97H9hL+FNhTc8SEZElF4/0QipBYr/XkVS37KUsb/79m1y+ehnTYuAKhLeHuffAvTQ0NngdnkjdU3I2UyyG6ziE9x1SgrZMLp+5TN/LfbQ80EJnqLhZX340z9tvvo2/yc/WvVs9jlBERGT1GR8b55W/fIWJOyfo7ClOySrkC5x47wSFlwo88LkHvA5RpO5pWuNcolHcwweIpCF1/BAJ5yAJ56DK8C6RY6lj+O/y0xxqrhzzt/ppu6+ND9/6EFuwHkYnIiL1Kp4KafnCTZz56AxjHWMEtwYrs1h8fh+h+0N88sknjA6PehyhSP1TcnYjpc2rM3/QQybZTSRNZZ8Ux3X0pX4bLqQv0LKxZdbx5lAzo9dGGc+NexCViIjUvVgM98UeQtk8qXTK62iqztC5IRrXN846bhoMpstw5eIVD6ISWV00rfFmotHKTQeIpxIkdwziZjJkyJFKp1T1aRGaA81M5iZpaJ4+d70wUcBX8NHg15x2ERFZJrEYsVSCxDqvA6k+5fZ5TtfA36TLRpHlppGzBYhHenFf7MFNhuhNBVT1aZHu3HUnV49frWykW3bl5BV6wj368hcRkeWXy2kWzAw9O3soDBYoTBSmHc8N5QhMBOja1OVRZCKrh5KzhYrFitUdVZZ30e647w42Nmwk84MMo2dHGTs3RiaVITgUZO9je70OT0RE6lw8E6msK9d68utC3SF27dzF8GvDXPnkCrmhHMP9w0y8N8HDTz+Mr0GXjSLLTUMUt2HmJtahQAiAWCTmaVzVzt/k59Efe5T0x2lOHT9FoVBg8/bNbLl7C42B2XPdRUREllQ0iuNAdHcfKX/a62iqhjGG3Y/tZsPWDXxy9BPGTo8R3hBm22PbaO1s9To8kVVBydntisXIJJNEn0lDIIMbyJFwDhIJ71cJ/pto8DewZdcWtuza4nUoIiKyGkWjOEmXUEzJ2VTGGNZuXcvarWu9DkVkVVJythRiMRzHqdzVHmkii1OYLHC6/zTuRy7j18bZuHkjd953J21dbV6HJiL1Kp8nmUpq1ovITVhrGRoY4sSRE2SvZOkIdbD93u2s7VESv9Q0eXipRKOVn6l7pGmxscj8FCYLvPE/3+CNI2+Q3ZJlcu8kH+c+5nt/+j0un73sdXgiUo9iMXqPBMmcH9D6cZGbOH74OIdeOsRQ5xCTeyc513qOl//Xy5x856TXodUdJWfLobRHWmTIX1lsXP4RkbmdPXaW01dP0/VIFy0bWmjqaKLz7k58e3ykXk7Nqu4pIrIUVOBL5OauZq7ywXsf0LG/g7aeNpo6mghuC9L+aDvvHX6Pa1eveR1iXVFytlymJGjh/jTh/nRlE2sRme2TY58QuCOAMWba8ZaNLQznhrl6+apHkYlIvVOCJnJj506ew260NDRN34fW3+KnsK7AhU8ueBRZfVJytpyiUZzu5ys/5akTStBEZpsYn5j1xQ/FxemmyTA5cYONUUVElkA80kvmhW3a/0xkhvxEHtNo5nzMNlq1z0tMydkKKvfMaW67yGzdPd3kzuZmHc+P5vHn/CoKIiIrIkTA6xBEqsqa7jXYC3bW8gJrLWbI0Lmx06PI6pOSsxWmqRMic7vjnjtoutBEdiCLLRQbgImrE4y8PcLuT+3G36TisiKyArJZUm4fib4Eib6ERtFk1Vvbs5Z1resYfn+YQr4AQGGiQObdDJvWblJytsSUnHmgMnVCCZpIRSAY4MCPHyB0McTwS8MMHxpm4o0JIvdE2P7Adq/DE5HVIBbDfbGH3lSA3j4IDRUTNSVospoZn+HRH3mUO1ruIPtSluFXhsm+nOWuzrt46IcemrVWXG6PuqK9EovRm0qQ2O91ICLVo31tOwd++gBjI2PkJ/K0drbS4J+9Dk1EZNnEYsRLN+OOQ3R3H6n89f1Ly0Khbu2NJqtGY6CRB55+gHvG7uHa1WsEggEaA41eh1WXlJx5LTd7jY3Ut2tXr3Hp9CUA1mxZQ3Nbs8cRVZ+WjhavQxARKRb2cgDXnX74mTSp/KA2r64zkxOTXBy8SH48T8f6DoJrgl6HVHWaWppoamnyOoy6dsvkzBizFfg9oBsoAN+w1v66MSYO/BxQrp/5S9bav16uQOtRPBUiuWOQhHOQSHg/0XDU65BkGVlrOfbGMfrf68eusVgsvu/72HP/Hnbs26FpASKyIGqfV0g0OuuQA8RTCRJ7B5Sg1YlzJ85x+KXDTAQnoAl4FXo29RD5bERrnmVFzWfNWR7419baPcB+4F8aY/aWHvvP1tpI6Udf/AsVi+EePkAom581XULqz+kPT3PkoyO0PdlG5wOdhB4I0XagjfeOvseZo2e8Dk9Eao/aZw+pAnP9yF7K8vpLr9P4YCOhh0OEPhWi89OdDOYGOXLoiNfhySpzy+TMWnvWWvtW6fYV4ENgy3IHtmpEo7gv9ngdhSwzay1H3zlK2962aXt5NTQ30LqnlaPvHPUwOhGpRWqfvacKzPXhk/c/wfZYmjqvT9czPkPHvR18cvITrl295mF0stosqFqjMSYMPAC8Xjr0C8aYd40xv2uM6Vrq4FaVfB7HdSo/Ul9swXJl5ApNXbPnaTevaWbk8kilfLyIyEKpffaOKjDXvktDl2heM3v9t8/vgyCMDo96EJWsVvNOzowxQeCPgV5r7Qjwm8BdQAQ4C/zqDX7vOWPMYWPM4Quj+sc9p3CYyJAft78Pt7+P1PFDJFNJr6OSJWR8hqbmJvKj+VmP5a/mCbQEMD6tORORhVP7XAViMTIvbCM0lCXhHPQ6GlmgtmAbE9mJWcdtwWJHLU2tKoAhK2deyZkxppHiF/8fWmv/BMBae85aO2mtLQC/DTwy1+9aa79hrd1nrd23vrV1qeKuL9EoTvfzuH37cfv203skSOZ8cZFx+UdqmzGGHXt3cOXoFay9PkJmC5bs0Sx37b3Lw+hEpFapfa4ipT3SQtk8CeegZsHUkDt230HezVOYKEw7nnWzrO9aT1uozaPIZDWaT7VGA/wO8KG19temHN9krT1buvvTgFZM3q5SRag4UUglcC6lIRAgFcyS6EvQu7/Xy+jkNt31wF1cOneJs6+dpaG7uO6scLbA5tBmbbIsIgum9rkKxWK4jkN43/V90VSJufqt6VnDPXvu4YNDH2A2G3wBH5NDkwRzQR74sQe8Dk9WmfnUBn0C+BngPWNMqnTsl4CvGGMigAVc4OeXIb5VKx7ppbi5CsRDKRJ7i3PZQ4EQgMr21qCGxgYe/cKjXBy8yFn3LD7jY+OTG1nbs1ZTGkVkMdQ+V6NoFNehsnk1KEGrdsYY7n7kbrrv7ObM8TOMXxtnzd41dN/VfdMy+tpGQZaDmTrFarnt27zZHn7uuRV7v7qSTBJ9Jg2AG8yTCfrpjT7vcVAiUs2+/pmvv2mt3ed1HFL91D4vA8cpJmjr8oTW9egivs4k+hKQzYLfr71qZcFu1j5rV71aEYvhlG8nk4SfLW5eHQp1AxAOhevyi6EwWWDgyADH3z/OaHaUzjWd3P2pu+ne0a1Nm0VEpHpFozhOaQSNwbocZTl/8jwfpT7i0oVLBFoD7Ni7gzvuv4MGf8Otf7nGOK6Dm3EByGTShLJ53Bd7CD87qCmssqQWVEpfqkRp8+pIGsL9aRgsfjHU2+Jjay1v/6+3eav/LSb3ThL8bJDRbaO89tprnHjrhNfhiYiI3Fyp4FdkyE9maLCuCnx98t4nvPLyK4xsGiH42SDcB6kTKQ7/zWEKk4Vbv0ANcVynmIANDhLuTxNJU9yjtnQ9Fsrm6/I6TLyhkbNaFY3iEC3eLk+dyB8ilU4BEAqEar6H7vKZy5w6f4quJ7oqa7JaNrTQ1NnEke8foWdPD82ts/clERERqSZO9/PEUwkSewfqYgRt4toE7/7gXdofa8ffWryUbOpsouvBLs70neHiqYusD6/3OMrbk0wlyeQyxTvZLJEhP07/gUrxNmKlJ5bXGEZSlZE1kduhkbN6EI3i9BdL8Pf2QcTN1UUPXdpNYzaZWcUyGpobYC1cPHXRo8hEREQWJh7ppfeDDjLnB2p+s+rLZy5T6ChUErMy4zP4N/s5c/KMR5EtjWQqSWZokIibo7cPeo8Ecfr3X0/MRJaRRs7qRTRaLMFfUg89dNbaG1YxtGblCtmIiIgshXikF1KJSgXmslrbKsdae8PufeMzs/YLqwVzjpR1Pw/d83yB3PWO8Vq97pLqoJGzOlUPPXQbtm5gMj3JzIqihYkC5qKha3OXR5GJiIgsTjzSS+aFbcURmT4IDWVJOAe9DmtBujZ1YTKGyWuT045ba8mfzbPpjk0eRbY4ib4EmfMDlc+k90iwmJjNVx2vLZSVp5GzOjazh67WeubWbV1Hd7Cb9Dtp2ne142/xMz4yTvb9LLt276KlvcXrEEVERBYuFiNeuhmfUoG5rNpLsze1NLH7vt0cOXyEtnvaaA41M5mbZOTYCOv869hw54Zpz0/0JSCXu+XrruR5T4tpfJzeDzqK1023od7WFoo3lJzVuVpO0IzP8PAzD3Ps8DFOvHaCbCFLS3MLD97/IHfcd4fX4YmIiNy+WAzXccB1AWqmNPvOh3cSaAvQ/3Y/mVwGv/Fz9667ufvhu/E1FCdmlasclsvO38xKnneiLwEjI2Re2Hb9YCy2JK9due5CCZosjpKzVSAe6b3eM1djCZq/yc+ex/ew69FdTOYn8Tf6b7gOTUREpCZNKTThTq3AXEpWQqHuqrvIN8aw7Z5tbN27lfx4ngZ/A74G3/Wy8yWhbB738AGIRW/6eq7jEN53aFkStDljenHbkiVkM8UjvTjpg7gbbv1ckZmUnK0WsRjulKkT1T5lYiZfg6/SEyciIlK3SptXl0fSos+kSeWL65jCoXDxWBW138YYXjn7SuV+6vihYjGN75QqaYTD86tyWC5JX0pMpz20iPOduufYnKN3y5SYTVUpMCKyAErOVpMpCVotTJkQERFZlaYkMw7FCszJHYO4mQwZcrgZt2pG0pKpJJlMmhAByOWIZPzFsvO3GCmbUykxje7uw833QSCwqPOdHRPFPcoWE9MiOd/prskZS+I9M7MS3nLat3mzPfzccyv2fnIDpakDmaC/5kbQRGT+vv6Zr79prd3ndRxS/dQ+14BkEoB4JENi7wh0dBDpjgAr19E6dTQKwM24xSqHH3QQT4WKB5dqRGrG+YY2bLvpyGE5NjfjFvcoW8zo3VIrdYhn1gWVoMk0N2ufNXK2Gs0xdUAJmoiISBUrJT1xgFSC5I4sbqaPjD9PKp1a9ov/RF8CsllC+SmXjvk8vcdLVQ4jS/yGM893fBA3nZ7zfMubRpdji2RKe5TFljimhYrFiKUSJNZ5HIfUFCVnq9WUqQMpDlXVFIlq4riOElcREakq8Ugvcccp3nHdynryUKg4UhQOhZek7Srv15XJZa5XNwyHpz9pBUakpp5vPJSqVKAOBUKV2Ho/6CCeiaxYTAuSy+l6QuZNydlqFo3iECWaPkgK7Wo/VaWyU35leiRFREQWZGqFx2SS6DNpyGRwAzlSmXTxKYtMBiol8HMQzhXXbTnfWb7qhvNSOt84UeLl8w1kIJcjmr79PcqWSzwTwUn3kUJr/WV+lJyJNk0scVwHN+MCFBcSZ/PEjgen9dABq/bvR0REqlQshlMeSYNKSfpymzafkbS52kD3xZ7rI2UrWEzjlmacb9WNlE1VnqlEcSmJZirJrSg5E2D6pomrsbJQeb56ZOj6fwmn/0DxCz+VwOnOAWlSa8ZX5d+PiIhUuWl7pRWXLZAujqCl1g3eNClwXKdSAr9ybIWrGy5YNSdkM01bSqKZSnJzSs6kopKglUaK6j0BKc+lB65Xdurff/0Lv1TkadpUiSl7xS313H4REZElUVq2ULk7ZfnCXG7WBsoSmbqUJJjxOhqpYtrVV6aJR3qLC35HiglavUqmkmTODxDuTxPuT9N7JFis7HSrnrhYDPfFHiJpCPenYbC4Z9zM8sIiIiLVwul+nt4jwUqbN/Nn3m2g3LZoOuB1CFLlNHIms8ViZKaMEPVGn/c6oiUxLdksV3Yqj4otpIcwFsMp33YcbUkgIiJV76YFMzRKtrJGVscMJVkcjZzJ3EojRKFsnoRzsOZHhhJ9iWJC1kfx54MlquwUjeL07ycy5Cd1/NANp4yIiIiIxCO99H7QUfczlGTxNHImNxaL4ZZG0FJu7ZWAnTlSlnlhmcoAz1joW37fUCCkBb8iIiIyTWWN/36vI5FqpORMbi4Wwy1P3auRPToq+7OUSuEDxFPLvD9LaaFvPJWoHFrtWxOIiIiIyMIoOZNbq4E9OiqbRpeEsnncwweuL26OrEwc06ZKlrcmcA4W7wcCml8uIiIixFMhkjvqa22/LA2tOZP5mbK2KjN043K8XkimksX9WdKQSXaTSXZPT8w8Uq58mUl205sKaH65iIiIFNXZ2n5ZOho5k/mbukeHx5soJlNJMpk0IQKQyxHJlPZnqbYNM0tTKeNAvFwBUxWaREREpMbX9svy0MiZLFh5v5TM+YEVHUFzXAfHdSp7lPWmArjJEO5/766N/VnKvWRD2UovWflHREREVqFYDPfwASJppi3PkNVLI2eyKJVKQwysyEhQoi8BuVxxpCybpfd4qRR+ZFnfdulN6SVz3RQAGXKAestERERWpWgUJ+kSiqW9jkSqQE0mZyPXrvHW6dNcGB6mo7WVB3p62NDW5nVYq04lQdu7PJsplkeUUunU9U2jUyEgtLyVF5dbqQImrgtA9Jl0ZRPrMiVqIlKLxicneTedxj1/nqamJu7ZtIntXV0YY7wOTUSkJtRccvbxpUv88Wuvce/EBLv9fi5MTvLN/n4+89BD7Ovp8Tq8VSce6SWeTBL66tKOoCWcg4SKA0qE8nncF0ul8CNL8vLemzIF0yltVeDmi9MZMv58VVbEFBG5meFcjuSrr7JxZIQ9fj9jhQLfOXaMTdu381P33YdPCZqIyC3VVHI2MTnJn/zgB/zDhgbumDJS9sDEBL/95ptsX7uWNS0tHka4SsViZMrFLhZZEtZxHdyMC1As9JHN477YA+Fw6T2iSxZu1SkVWsFxindLm1lrjzQRqSV/+d57PHjlCk+GQpVjDxUK/N7x47yzfj0PbNrkXXAi1cxxiD6jKY1SVFMFQY5evMimXI47AoFpx7saG4lYS+rMGY8ik9spCVveoyzsZgi7GSJpiqXwY7HiCFO1F/pYKqVz9argiojIYl25do3BM2fY394+7Xijz8eTgQBvnzzpUWQiVa40eya1Lk8o1O11NFIFamrkLDs+ztobPLa2oYHTY2MrGo/MUFpLFd536JYlYacmHZmhQSJDfpz+yPUnrJaE7AZmFlwJBUIAGkkTkap0dWKCDorJ2ExrGxvJjo6ufFAitcB1SUUhEj6g9eYC1FhytrGtjbcBa+2sxcXu5CQ9nZ3eBCbXRaO4TmlqXqnIxcwvm2QqWUnIikp7lK3yhGymcoLmdOeANKk149ojTUSqUlcgwHBDA9nJSYINDdMec3M5Nm7Z4lFkIjUgEFBiJhU1lZyFQyHM2rUcunSJAx0dlQTtw6tXOdnSwhc0n706RKM4Tnnt1KHKWrKyzPmBYuXFSO/1gxrJn9O0v6Mp6/rKUx/CobC+0EXEc81+P5EdO/iLDz/k2c7Oygja0MQELxUKfHH7do8jFBGpDTWVnBlj+MrDD/OtN98kdeECW43hgrVcbW/nq488QsBfU6dT30oJWjyUwum+vsg1mg4AMxIzmZ/SHmnxSAanO40bzJPKFP9ulaCJiNc+d/fd/MX4OP/5xAl2GMMYMOj388OPPMIdU4qEiIjIjdVcNtMZCPAvHn+cwZERhkZHube5me1dXSrRW42iUeJEpx/TCNnticWIl2/Pc32fiMhK8Pt8/PT993Np504Ghodp9Pl4ds0amtVxKjK30owYCHodiVSRmvzGNMawtbOTrVpjJotUsJZz2SyW4lrGhjkWsVe9eazvExFZaWtaWrStjdyWi6OjjOXzrGttrd9ZUaU9Yuno0FpymeaW/+KNMVuB36M45lEAvmGt/XVjzBrgfwBhwAW+bK29vHyhiiyND86f52/feQf/1av4gLGWFj573308sHmz16Et3Iz1fal0CoBQIKTKjiJ1Tu2z1Jtz2Sx/8c47DF+4QIcxXPT5eODuu/nczp212Yl6E/FIRomZzGk+/9LzwL+21u4B9gP/0hizF3ge+Dtr7U7g70r3RaraicuX+Z+vvsoXJyf5hVCI/z0U4h8bw0uvv8775855Hd7iTNkbrbcPevvQHmkiq4PaZ6kb2fFxfv+VV3jw0iX+VWcnP9fZyS+0tnLhgw/4Tn+/1+GJrJhbJmfW2rPW2rdKt68AHwJbgJ8Evll62jeBn1qmGEWWzMtHj/LDjY1snbKReXdTEz8RCPByfz/WWg+juz3xSG/lp/eDDjLni3ukiUh9Uvss9eTw4CC7x8Z4sL29Ukcg2NDAs52dvHf8ONnxcY8jXFrxVIjQUJaEc9DrUKTKLGiM2BgTBh4AXgc2WmvPQrGBADYseXQiS+zU+fPsmmMtxJ2BAJcuX2Z8ctKDqJZeOUFjZEQjaCKrgNpnqXWnzp9nV1PTrOMBn4+t1nJ6ZMSDqJZRLIb7Yg+hbJ6EcxDHdbyOSKrEvJMzY0wQ+GOg11o77/8hxpjnjDGHjTGHL4yOLiZGkSXT5PczWijMOn7NWvD56mdOu+MUN6/2+QiHwl5HIyLLSO2z1IOmpqY522eAq0DTjM3N68KUBC3l9ilBE2CeyZkxppHiF/8fWmv/pHT4nDFmU+nxTcD5uX7XWvsNa+0+a+2+9a2tSxGzyKLde+edvJrNzjr++pUr7Nq2DX+dJGfR3X2kuiGy44AqOIrUMbXPUi/u7enh9YkJJmcsL/gklyPb0lK/e+XFYriHDxBJQ+r4IRzXqfzI6nTLK1FjjAF+B/jQWvtrUx76c+BrpdtfA/5s6cMTWVrRu+7ieGcn3758mU9yOU7lcvxVJsNbbW18bvdur8NbUqFQtxIzkTqm9lnqyZ716wmFw3wzk+Ho6Cjp8XEODQ/zrYkJfvyhh+p7P9toFKd/P5EhP25/H66bIuX2aVnCKjWfzSOeAH4GeM8Ykyod+yXgIPAtY8zPAgPAl5YlQpEl1NbUxL84cIA3Bgf5m1OnsNayc8cOfm7bNoJzzHUXEaliap+lbviM4dlIhHc3beK1kycZu3aNzZs380/DYTYGV8EmzaWtcXDd4t1n0qRI47iOOlpXmVsmZ9baQ8CNuiueXtpwRJZfS2MjT915J0/deafXoYiILJraZ6k3PmOIdHcT6e72OhRvRKOVm04ySTiW8SwU8U6dbru+ug3ncrw+MMDAuXM0NTZy7x138KmNG+un2IWIxzLpDO77LiMjI3R0dhDeGybUHfI6LBGpcuOTk7x15gwfnjpFoVBgx5YtPNzTQ2tjo9ehSbVwHKC4SXWGnLex1KDR4VEGPhjgQvoCTc1NhHeF2XDnBoyvdqbFKjmrM2evXOEPDh3iU9eu8UOBAGOFAn1nz/J+Tw9feeihuil4IeKVT977hLcPv43vDh/NdzSTyWRw/6fLg488yLZ7tnkdnohUqVw+T/K11+gaGuLJQIAG4L133uG/fvwx/+zAAUJT9t+UVchxiO7uw91fvJvx5wmFejSlcQEy6Qyv/M9XyHfnad7WzEhuhDOvnyHshol8JlIzCZqSszrzl++8w+cnJ/nUlKpGd7e08AeDg7y9aRMP9/R4F5ysiHgqQerePCGvA6lDuWyOd37wDsHHg/hbil+fzWuayXfnSb2WYmN4I81tzR5HKSLV6PsnT7JpaIifCIUwpeIWd7a08NLwMN/t7+dLkYi3AcrKc5zpa8zW5YnsOFB5WInZ/Flrect5C7PH0NndWTneuqkV9zWXLZ9sYcOdtbHlo5KzOnJxdJSRoSHu6+ycdtxnDI8HArzkukrO6lw8lSCxdwSCHcQiMa/DqTvnTpyjsL5QSczK/K1+CusKnD95nq33bvUoOhGpZu+eOMHXgsFKYlb2aHs7vzYwwMR999FYj3t5ydySScLPDkK0WOwkA0TC2v5msa4MXWFkYoTOjdOvgY3P0LitkYGjA0rOZOXl8nmCxsxZbjbY0MC1iQkPopIV4zg4u3PQ0UHv/l6vo6lLE+MTcIOBMdtki4+LiMwhNz5Oe1vbrOPNxuArFJgoFJSc1btksnIz/OwgmaCfSDhSOabEbPHy43lMk5nV+QHQEGjg2qVrHkS1OErO6sj6tjYyfj/D+Tyd/ukf7bGxMXq2bPEoMlkxgQChQMjrKOpWaEMIPipOn5jaAFhrMZcMnfd13viXRWRV27phAx9duMB9M8rCD167Rmt7Oy1+XZLVtWSS0FcHoLJtj5/e6POehlRPgmuCmKxhcnyShqbpnRzXzl9jw6baGDUDJWd1pamhgUd27eKP332XL3d2EmxowFrLx7kcrzU0EAuHvQ5RlkE8lSjeCEEqmCWk1WbLZm3PWtY0reFy/2U67u7ANBjspGX4o2HWtaxjzZY1XocoIlXqwN138+2zZ1l77Rqbm4tD8BcnJvizsTGevP/+OXv8pX7EIxnNbFlGTS1N7Nizg/63++mMdNLQXLwGHj0zStOFJrZ+unaWHCg5qzOfvusuCtbyX44eZcPkJKPWUmhv50sPPsiGOaZTSA0rVXZK3ZuHUk9sKNCjtWbLyPgMj/7oo7z70ruceekMtAFXoWdzD/f/iC6uROTGtnd18cOPPcZ/f+cdWoeH8QOXGht56qGHeGDzZq/DE6l5ux/djc/4OHboGIW2AvaaJdQa4sEvPEggWDvVUJWc1RmfMTy9cydP3HknZ69codnvZ9McC5ClRjkO8VCqeHN3rlLZSfPUV05zazMP/8jDjF0ZI3clR6A9QEt7i9dhiUgNuHfjRvZ87nOcuXKFgrVsbm/XOrNVoFKsiw6vQ6lrvgYfux/bzV0P3EX2chZ/k7843bHGroGVnNWpgN/PnV1dXochS6lU2SkT9EMgAASIdEeUmHmkpb1FSZmILFiDz8fWTq1PXS3KiVlowzbNbFkhjYFGujbV7jWwkjORapZMFuepA8lns6XKTvuVkImIiNSKDm1vI/On5EykWpUrO3WUp0EEtZBYREREpI4pOROpIvFUAqc7B0Dqq+Oq7CQiIiKyiig5E/Ga4wAQD6WKC4Y7OggFigXxNQ1CRESkRjkOzu4cUDuVAsV7Ss5EPBRNH4RI8Us7FcwSWqcFwyIiIjWvvN1NN0S6I15HIzVEyZnISiqNkgHFL+11eULrQgCECCkxExERqQOVxExFvGSBlJyJrJRSL5obKt7N+LVHmYiISL0KhbrVxsuCKTkTWU7lkTLXrexRFgnvrzysL20RERERKVNyJrJcSptG4/fDfsgEtEeZiIiIiNyYkjORpZRMVm6W9ygrLwRWUnZr+fE8A+8PcPLoSSbGJ9iwaQM7IjvoWN9x618WERGRZWGt5eyxs3z8/sdkR7J0hDrYcd8ONty5AWOM1+HVFSVnIksknkqQfDYLwSAZchDQHmULMTkxSd9f9XHBXqB1Vyv+gJ/Bs4MM/sUgT/zQE6zdutbrEEVERFal/lf7+fDkh7TsbKFxdyPDmWFePfQq9166l537dnodXl1RciZyO0ojZfFIprJHmUbKFufMR2e4kL9AaF+o0gvXsb2DsfYx3v7+2zz9lafVOyciIlUvnkqQ2jtOyOtAlkj2UpajHx0ldCCEr9EHgL/FT/OaZj449AE9u3poaW/xOMr6oeRMZJGi6YOk/km+uKYMCIW0R9ntGDg+QOCOwKwELLAuwPCHw2QvZmlf1+5RdCIiIrcWTyUqnbX1ck1w7uQ56KaSmJU1NDdg11uGPhli671bPYqu/ig5E5kvxyEeShVvdudKe5T11M2Xr9cmJycxDbNHxowxmAZDYbLgQVQiIiLz53TnCG2or87ayclJaLjBgw2ofV5iSs5E5sNxCO87RCboh0AACBDpjmjq4hLatHUT7595n8DawLTjE9kJGicaCa4NehSZiIjIPDgORAK3fFqtWbdlHfaoxe6002a32IKFC9D1SJeH0dWfFU3OzoyeJ55KTDsWj/SuZAgi85dMEo9kijf3ZSt7lCkhWx7b9m7jRP8JRj4eoT3cjmkwjA+Pk303y4MPPUiD/0bddiIiIrJcujZ3sSm0ibPvnKVjTwcNzQ3kx/Jc+eAK2zZt05KDJbaiydn5ICT2TzkwMgKphBI0qT6lPcquj5QFNVK2zJrbmnnyJ57kyCtHOPu9s+CHFn8LDz/0MD17erwOT0REZFUyxrDvh/dx9AdHOXHoBAV/gYZCA3t272HnwztVrGuJrWhytqFtA8/tf65yP5lKkvAN4qQPEk3f3jBwPBWCWOz2ApRVbeqobuKrxcW8KoW/slo7W3nkRx9hIjdBfiJPoC2A8elLX0REqpzjEN3dRyqYJ1Q3dRqv8zf5uefAPex+dDfjY+M0tTTR0KgZLcvB0zVnsUiMZCpJKpghFb6910rsHSCTTCpBk0WZWl2pSImZlxoDjTQGGr0OQ0RE5NbKiVk3RMIH6nqWTUNjAy2NKpu/nDwvCLJU1WwSfQlCXx0gkj5426/l9O+HaPT2g5KqFk8lcLpzAMX9SOqsupKIiIiskECAUChU14mZrAzPk7Ol0ru/l2Qqibvh9l4nk0kTDh7CdaYcVKJWHxyncjO6u4/UvcVS+AAhlq6jQERERERkMeomOYOlubh2XIeU20d4fx/hXAByOZykq+mSta405aBY3IPinHDtUSYiIiIiVaSukrOlUB6OdjMuLqWRtGcHcbWerfZMGSkr71EWCoUAiIRUeVFERESWgOvi7s95HYXUCSVnc5h50V5ez6aCIzWkVAoff/GfeCagPcpERERkiSWThL46UKzwrNk4sgR8XgdQC3r390JHB6GvDszaRFuqiOMUf6bsURbevZ/w7v1KzERERGRpOQ7RZ9LaekeWlEbO5ql3fy+JvlK5dW2cXXXiqQTJfVnw+8lEgUBQX5QiIiKyvAIBQoGQ11FIHVFytgDlipAJBpSgVYNkEoB4JFPZoyzSHQFmT00VEREREal2Ss4WqLxxdsI3iJM+iNP9vNchrUrxVILks1kIBsmQIxTSHmUiIiIiUttuuebMGPO7xpjzxpgjU47FjTGnjTGp0s+PLm+Y1SUWiRFa10NqXZ5o+uC0qoCyTEpryUgmiaYPkrg3Cz09hMMRIuH9SsxEZFVSGy0iUl/mM3KWBP4L8Hszjv9na+2vLHlENSIWiRX3ROMQ0d19xfxMm1Uvj9IeZakD+Ur1xVBIe5SJiKA2WkSkrtwyObPWvmyMCa9ALDWnvK4p5e8jHDyE66AEbak5TmWPskj4gNaSiYhMoTZaxCPljuNgnhAhr6ORGpLoS9z08dsppf8Lxph3S1Mqum7jdWpaNBwlEt5fLNu+71ClSIUsgWRySmKmUvgiIgugNlpkuZQTs3V5Qus0k0fmL9GXgJGRmz5nsQVBfhP494At/fmrwD+f64nGmOeA5wA6N3Yu8u2qW2UEze0j/OwgrjarXhrhMDDodRQiIrVmXm301PZ5W2d9ts8iyyYQILQupMRM5uS4Dql0atbx0FAW98VtGD654e8uauTMWnvOWjtprS0Avw08cpPnfsNau89au6+1s3Uxb1cTouEovdHnyawLEn52UCNoSyEaxT18gEgaUscP4biO1xGJiFS9+bbRU9vn9a312z6LiKwkx3VIuX2EhrL09jHtx32x55YDOIsaOTPGbLLWni3d/WngyM2ev5pEuiO4uZTXYdSPaBTHoTh9gEO4GVe9VCIiN6E2WkRkZZUTMgDyeSJDfpz+A7NrUURu/Vq3TM6MMX8ERIF1xphB4JeBqDEmQnHKhAv8/HyDXw0y5IhHMsS9DqReTEvQBnFcR+vPRERQGy3iCdfF3Z/zOgrxWHlGl5txyQwNFhOy73QXHwyHF10kcD7VGr8yx+HfWdS7rQLRcJRUOkVi7wikEsQjvV6HVB9KCVp4f5/XkYiIVA210SIrLJkk/OwgmYCfXs3kWbWSqSSZTJoQAcjliGT8ON3PQ+z2X3uxBUHkJnr395JMJUkwoARtqeXzuBnX6ygWzVrL5TOXOT9wHoAN2zbQtbkLY4zHkYmIiKxu57JZ3j5/lmx+nB0da7ln/XoaGxquP8FxiD6TJrMuSKQ7opk8q0x5pCyVTsHICL0fdBBPhYoPLmEhQCVnyyQWiRUTNN8gTvpgMZuW2xONEkulSDQNkOhL0Lu/1+uIFmQyP8lb332L00OnMd3FZKz/7/vZsm4LD33+IXwNt7OzhYiIiCzW35w8zn8/ewSzydDQZvjL88focTv41596jK6WluKTolGiqRRuMIub6SPjz5NKp2ruekQWLtGXgGyWUN5PKJ8ndryjOPgSWfr3UnK2jMoJWopBoumDOP37tUn1bYpHeiGVIHFvlmQqWVPFQU6mTnLq6im6nujC+IrJmb3LcurNU6xJreGuh+7yOEIREZHV5+NLl/ij80fY8nA7jY2lkbItcPrUCMn+FP/qgccqz41Heok7TvF2qLiMJdGXINIdmfaaGlGrTXNVBi+PlGVe2Fba5ollvZ5XcrbMpiVou/twHJSg3aZ4JoKTTeGu8zqS+bPWcvz947Q/1F5JzACMzxDcFeR46riSMxEREQ+8dPYTmrY2XE/MSjb3tPPuqXMMjY6ybup2E6XruDhR4skk0WfSuJnpa+ITbh+R8H4laTWkUgJ/Rq2XSAac72xbsT2MlZytgFgkVvzAOaQEbankcmRyGa+jmDdbsORyOULB0KzHGtsbGR4dxhbstMRNREREll/6Wpa2tsZZx40xNLQaRq5dm56cTRWL4ZRG0ipcl/Czg6Tcvso6+XAorEStCjmuU/mMMpk0oWwe9/CB2U+MRVcsJiVnK6T8HzLl7yMcPITroARtsaJRnGTxiy/hHKQ3Wv3r+YzP0NbexrXL12juap722Pjlcdo725WYiYiIeODO1hAnRi7T2RmYdnxyskDhKqwtrzm7kTmu51zHIbq7DzIZAFLBQ8WnKkGrGslUslgCPxssHsgx995kK0zJ2QqqJGhuH+F9h3CT7ooNkdadWAw3mST8j9I1sfbMGMOu+3dx+N3DND7ciK+xWPyjMFHg6odXefiBhz2OUEREZHX69JYw333vBKNrJ2htLY6gWWs5dWKEJzu30RkI3OIV5lDaAqhyd3cfKQ5Nqzhd7dcuU5VHmGop5rkkU8nK7creZP2R60+ogoETJWcrLBqOEg1HSTgHCT87iJtMKkFbrHCYcC6D63Uc87T1nq1cHbnK0ZePQmm9nBky7N27l549Pd4GJyIiskptbm/n/7n9Ef7rW29yoesqNIG9BA80d/PVe+5b/AtPudB3iBJNH4ShNACpNeM10bkMU9ZiZfMkMrUxY2kuyVSSzPkBIpeaAIimg8VCc93exjWTsdau2Jtt3rXZPvdfn1ux96t2ib7E9eovStAWrjRlINVNTS26HRsZ4+LgRYwxrOlZQ0v7LaZLSFVzXKdYyakKDf/b4Tettfu8jkOq377Nm+3h59Q+y+o2NjFB/9AQuXyeno4Oejo6lm0f0ngqQWLvCHR0VI5VU0n+aW1bLkckDc53uosbcAf9sJjRRK+V9yargv2Hzde/fsP2WSNnHurd30uiL0HoqwP0arPqhStNGYjSRypfO3O5Wzpa6NmrkbJ6MLU3MXY86HU4s3zd6wBERGpIS2MjD2zatCLvVd4aqKxckr8aErTKWqwhP9F0AAgQz0QgFsVNJolHMh5HuFjVkZjdipIzj5UTNFmkcoI2ZS53LUwRkNqTTCVnVwjN5a5XdqqCeeozff3PlJ6JiFSrqYlCPJkk9NWBOa8JI92RZe98ntbGZbPFtVjdz8+e8heLEV/WSETJmdS+aQnaYM3M4ZbaMbsXsazUm1iFiZmIiNSQWIzMHKNSyR1ZUrniHmrLlaCVl9n0flCeYhmsiRGmeqXkTOpDOUGL1Nbm1FK95t2LKCIishTmGJWKOw7hfYdIuX2VNWBLMZI2bYSuitZiiZIzqTe53K2fI3ILM3sR46keFe0REZGVF43iOhAPpQBwunOksre3jGN2G6fCdNVEyZnUj2iUaCpFYs1A1SyqldqR6EtcT+7Hx6f3IkY8CkpERCQaJU70+t30QVIMknAOAhAKdd80USsXryoLZfO4L05JyCJLH7IsnpIzqSvl6keJvSNaeya35LgOQKXiovvilCqa6kUUEZEq5HQ/D8kkAPFIhsTeAZKpJOFQeM7nq42rLUrOPJZwDhLK5ovTpiJeR1Mf4pFenPRB3A1eRyLVqlICn2Jxj0qjpcZKRERqQam9igOkEiTHB3EzmdnPy+WIZMDpPwCx6EpFJ7dByZmHEn0JXRQuo1llz+W2lUeabqba9pqbK+brvYih0pGQ/g+KiEhNikd6iZdG0uYUDquqcA1Rcuax2PGgLgqXQXkX+4RzkN7o816HUxcSfQnIZgnlb/y1kfHnSaVTVbPer1wCf2bM6kUUEZG6omvJulE1yZm1lkunL3Hq6CmuXbvG2o1r2bp7K81tzV6HJrUoFsNNJosJmoqDLJrjOrgZtzgKOTJC5oVtxR64G3HdSlIcCnUTDoVXfCStHDNQ2ZvM6d8/+4nqRRSZt3PZLK+cOcWpsWG2tLTzxKZtbGpv9zosEZG6UxXJmbWWDw59wEcnP8K/zU/DmgbOnjnLsfeO8cQXnqBjfcetX0RkpliMWCpBQvueLVhlTVYOwrkA5HI435lfqV03mST6TBoyGdxAHwm3j0h4/4okaeXRvUg2CLkc0XRpI03tTSayaG+lz/IbH/8AuwWC65p498o5/vq94/x8+CEe3dxz6xcQEZF5q4rk7OKpi3zkfkTn4534/D4AWrtbuXr6Km9+702iX4pijPE4SqlZuRyO61TdWqhqM23EKZO+vh6yPFI23ymAsRiO41TuljfPLL/2Uo+mJVNJgMroXu8HHcQzkeKDGh0TuS1Xx8f5reOHWftgK62tjQCsWdPC2IYJ/tubb7Fn7Xo6mjXDRURkqVRFcjZwdAD/Nn8lMStr3dzK8MfDXBm6otEzWZR4JoKT7iOVPwRUX7GKauG4Dqnjh4ojTgC521yTNSUpch2I7u6DUhWpVPD2Ns+cauZI2XxH90Rkfo6cP8+1tZOVxKyspaWR8fVZ3j2X5sC2OzyKTkSk/lRFcpbL5fCHZodijMEEDBPXJjyISupCNIrjFJODFEuXFNSD8ogTTF2bFSkeiEaXbipgNIpDFEqjacXPYnDa+8/3M1my0T0RmZfR/AQmYOd8zBcwZCfUPouILKWqSM7WbljLhQsXaFnfMu14YaIAIxDsCnoUmdSFUnIQTR+sJAWrPUFLppJkzg8QudRUOuIvbmq5nGuzSqNpDlHiqQROdxqA1JrxeX0mlXVw2TzhbPGry/mOtqEQWU6bg+0wYODO2Y/Zy9CzWbNaRESWUlUkZ9v2bOP4Hx9nbN0YLRuKCVohX2D43WHu2nGXKjbKknC6nyeeSpDYn/E6FE8k+hLX75TXZkV6PYll6vvGUwkSDEyPby7ZbGl078D1aZOxZQpQRADYuXYt20908cknGXq2dWCMwVrLmcErbL3WyZ51qrgkIrKUqiI5a+lo4fFnHufNv3+TzLEMptnAMGzfvp17DtzjdXgiNS/Rl6gkZEXeJWYzxSO9kErM45nBYqEPFfkQWTE+Y/jF+x/ldz58m/fOnsMXNBSylj2N6/m5+x+kwee79YuIiMi8VUVyBtC1qYunv/I0w+eHmbg2QfvadgLBgNdhLZvyxTJoSsiKGxlZFXufzRwpy7xQvcUyqiVRFJHZOgMB/o8HHiOdzXJpbIyuOwJ0B4OqoiwisgyqJjkDMD5DqDvkdRjLbuoohi5KV1Z5lCaxt34TtKlrs2LHi+s146nqTcxEpDZ0B4N0B7UGXERkOVVVcraaKDHzTiVB2+91JEvHcR1S6VTxTi5XrGJ4eMrarIhHgYmIiIjIvCk5E6lxlT3Khvw43ymVWwyHtTZLREREpMYoOZNVKZ4KkdwxSMI5SG/0ea/DWbBkKkkmUyxFTz5fqmK4X/t8iYiIiNQwJWeyOsViuMkk4WcHa2btmeM6ALgZl8z5geLU2FSo+GAstrx7lImIiIjIslNyJqtXLEYslSBRA9v0JPoSxbVkBCCbpfd4ac1ixOPARERERGTJKDkTyeVwXIdoOOp1JNOUR8pS6dT16p6pEBBS5UURERGROqTkTFa1eCaCk+4jlT8EUDUJWsI5SChXvB3K53FfLJXCj3gZlYiIiIgsJyVnK8xxHchmAe0VUxWiURwHorv7SHEIN+MSi8RWPAzHdXAzLgCZTLpYCv/FnmLVRVChDxEREZFVQMnZCkqmkmSGBokM+YlnIl6HI2XRKA5RoumDpBgkmUquaIJW2TQ6B+FcAHLg9B9QQiYiIiKyytwyOTPG/C7wY8B5a+29pWNrgP8BhAEX+LK19vLyhVkfMrnM9ZLndboH1blsltdOnmTw/Hmam5q4PxzmoS1b8Pt8Xod2S07388RTCRKR9LKvQUumkpXb5YTd6Z+yK3ad/vsQkaWlNlrm6+r4OH0DA3w0OIi1lrt7enh02zbam5u9Dk1EppjPFXMSeGbGseeBv7PW7gT+rnRf5iGaDtTthfeJy5f55ve+x7oTJ/jy5CRPZ7McO3yYP3zjDfKFgtfhzUs8FSpWRFxG5RHUsJsh7M5I2Ms/IiLzk0RttNzCyLVr/Pb3v8/YkSP8xLVr/NT4OBPvv89vv/wymVzO6/BEZIpbjpxZa182xoRnHP5JIFq6/U3AAf7NUgYmtcVay1++9RZf9Pu5q6UFgA3AnYEAv3/mDO+k0zy0ebO3Qc5XNksqnVrSkbNpI2XlPcrKU1ujUe1RJiKLojZa5sM5fpz7rlzh6VCocmxzczOtw8P83dGjfPFTn/IuOBGZZrFzzTZaa88ClP7csHQhSS06m83SkM2yPTB91MkYwyPNzbw/MOBRZAsUixE7HoSRkeLeYksg0Zcgc36AcH+acH+6mJhFejVKJiLLRW20VFhrOXLyJI+2t8967JFgkA8/+YSCtR5EJiJzWfaCIMaY54DnADo3di7324lHxicnaaGYjM3U6vMxPjGx8kEtUjzSSzyZJBRb/NqzaYldeY+ySG/xvkbJRKQKTG2ft3Wqfa5nE/k8LXOs/W72+bCFAgVr8c3RfovIylvsyNk5Y8wmgNKf52/0RGvtN6y1+6y1+1o7Wxf5dlLtNgWDnG9o4Eo+P+uxD3M57uiuvYxksWvPEs5BQkNZevugtw8yL2y7npiJiCy/ebXRU9vn9a1qn+uVMYZtGzfSPzo667FjY2N0r1tXE0W7RFaLxY6c/TnwNeBg6c8/W7KIpCY1+/08sns333r3Xb7Y0UHI76dgLe9evcq7zc08t3Wr1yEuXDZLyu0Dbr45teM6pNKp4p1c7voeZbFY8VhkOYMUEZlFbbRM89SuXfzpyy8TzOXY1tyMMYZTuRx/NT7OF3bv9jo8EZliPqX0/4jiwuJ1xphB4JcpfuF/yxjzs8AA8KXlDFJqw2fuuosGn49v9PfTfvUqV4HQunX8zKc+RWdgeSsgLrlYDDeZJPzs4E0TtMoeZdl8ca0agWKhD+1RJiIrQG20zMdda9bwo48/zp+99x6MjGCAydZWPv/YY+xat87r8ERkivlUa/zKDR56eoljqWsJ5yChbJ54qqduR1KMMXx6+3Yev+MOhkZHCfj9dJUqN9akcoIWy0w7nEwlyWTSxTv5fKkU/gEV9xCRFac2WuZrz4YN7P7sZ7kwOoq1lvVtbVpnJlKFlr0giBSLQ8ya6lbHGhsa2DRHVah6UN6jLDLkx/lOaR1dOKzETEREqp4xhg1tbV6HISI3oeRsJeRyqyYxqzvhMOF0H6n8oeL0xvHx65UXY14HJyIiIiL1RMnZMnNcx+sQ5HZEozgO4LrXjynJFhEREZFloORsGZWLRUTSFKe+SW3SlEURERERWQFKzpbJtLVJ/ft1gS8iIiIiIjelXQeXgRIzERERERFZKI2cLbFpiVn389DtdUQiIiIiIlILNHK2hJKpJJnzA/QeCRYTMxERERERkXlScrZEHNchk0lfL7MuIiIiIiKyAErOllCIAPFUyOswRERERESkBmnN2RJJpVOEslkg5HUoInNKZ7O8fOwYx0+fxhjD7q1b+fTOnaxpafE6tJpSsJY3Bgd549gxLmezdAWDPHL33Ty8ZQvGGK/DExGRGnN1fJyXT5zgvZMnGZ+YYNvGjTx5993c2dXldWg159jFixz66CNOX7hAoKmJ+7dv56nt2wn4ayflqZ1Iq1iiL0FoKIv7Yo82KJaqdHpkhD/8/vf59OQkP97WxiTw1smT/O7Zs/zzp55SgrYAf/H++1z66CN+srWVTe3tnLl2je/+4Aec27WLH7/nHq/DExGRGjI2McHvvvoqd12+zM8Fg7Q1N9N/4QJ/nE7zhcceY8+GDV6HWDNSZ8/yvddf54cbG9kRDHJlcpJD779P8tw5/vnjj9PU0OB1iPOiaY23wXEdEs5BJWZS9f7uww/5oUKBRzs6aGloINjQwFOdnTycy/Hy8eNeh1czzl65wsfHj/NPQiG2BgL4jWFbIMDPhEJ8dOwY569e9TpEERGpIW8MDtJz+TI/2tVFV2MjTT4f9weDfKm5mb99910K1nodYk3IFwp89513+GprK3vb2mjy+Vjb2MhPhEJ0Dg2ROnvW6xDnTcnZIjmuQ8rtI5TNKzGTqjY+OcmpdJr7gsFZjz3Y1kb/qVMeRFWbjg4Ncb+1NPqmf3U2+Xzcay39Fy54FJmIiNSi/lOneHCO2SvbmpvxXb2qTr95GhwZoevaNTY2NU07bozhweZm+gcHPYps4TStcRGmJWaHD0As6nVIIjdkrQVr5+yJaTCGQqGw4jHVqoK1+G6wrqyh9LiIiMh8WWtpmKNdMcbQYK3alXkq3OA6B2rvWkcjZwvkuA6p44eIpCkmZtGo1yGJ3FSz30/3+vX0j47Oeuzdq1fZuWWLB1HVph1r1/I+MDmjsZy0lveNYefatd4EJiIiNWnHli28OzY263h6fJyxlhY2trV5EFXt6eno4ILfz+WJiVmPvZvL1dS1jpKzBUimksXEbMiP079fiZnUjM/s3ctf5fN8cPUqBWvJW8tbV67wckMDT+7c6XV4NWNrRwfrtm7lxUym0gBcmpjgW5cv033HHWzp6PA4QhERqSWPbN1Kf1sb3x8e5lqhgLWWk2Nj/I+rV/nMfffR4NOl+nw0NTTw1H338cKVK5zK5bDWMjY5yd8PD3Oqs5MHN2/2OsR507TGeUqmkmSGBouJWffz0O11RCLzt72riy8+9RTf++ADvn3hAhjDtk2b+Cd79tA9x1o0mZsxhi898ABORwe/ffw4hatX8TU389D99/Pp7du9Dk9ERGpMe3Mz/+zAAb7b38+vnDqFr1CgMxTi6Qcf5N6NG70Or6Y8tm0bAb+fP+3vJzs8jG1oYPedd/LPdu2ipbHR6/DmTcnZAkSyQZz+iBIzqUnbu7rY/sQTXMvnMcbUTEnZauP3+fjczp18dscOcvk8Ab//huvQREREbqWrpYUvP/AAE/ffT75QIOD3a9/MRXpg82YimzaRy+dpbGjAX4Mjj0rOFiKX8zoCkdvWXEMbMVYznzG01lBPnIiIVLfGhgYa1XF624wxNTVSNpOu0uYh0ZeAkRGi6Q6tMxMRERERkWVRe2N9K6ycmPV+0EE80ut1OCIiIiIiUqc0cnYT5cQs88I2bTItIiIiIiLLSsnZDSScg8VNpl9UYiYiIiIiIstPydkMjuuQcvtKiVmPEjMREREREVkRSs5mcDNuMTE7fABiUa/DERERERGRVUIFQeYQzvpVlVFERERERFaUkrMpHNchMzTodRgiIiIiIrIKaVpjSTKVJDM0SGTIj9O/H7q9jkhERERERFYTJWfMSMy6n1diJiIiIiIiK27VT2tMppJkzg/QeyRYTMxEREREREQ8sKpHzsqbTPd+0EE80ut1OCIiIiIisoqt2pEzJWYiIiIiIlJNVuXIWTkxy7ywTZtMi4iIiIhIVVh1I2eJvgShoawSMxERERERqSqrLjkDiB0PKjETEREREZGqsqqSM8d1IJfzOgwREREREZFZVk1y5rgOKbePUDZPPBPxOhwREREREZFpVkVBEMd1SB0/VNxkuv8ARKNeh1QVrLUcv3SJD86cIT85SXjDBu7fuJHGhgavQxMREVnVzmWzvH36NFdGR9kQCvHg5s20Nzd7HZaILLPbSs6MMS5wBZgE8tbafUsR1FJKppJkhgZLidl+JWYlBWt5MZXi4ief8KDPR7PPxweuy6uhELHHHlMDICJS42qhjZa5vTYwwCtvv80+YEtDAwMDA/zmhx/y5ccfJxwKeR2eiCyjpRg5+4y1dmgJXmfJKTG7sTdPn2b05Eme6+qiwRgAIsDfDw/z1++/zz988EFP4xMRkSVRtW20zO381au88vbbPNfWRoe/eJl2H7BnbIwXX3+df/VDP0SDb9WsShFZder2f3c5Mes9EsTpfl6J2QxvnzjBUy0tlcSs7In2dk4ODjI6MeFRZCIiIqtX6vRpHoRKYla2vaWFtWNjHLt0yZvARGRF3G5yZoG/Nca8aYx5bq4nGGOeM8YcNsYcHh0evc23mx/Hdchk0vQeCRKP9K7Ie9aa7NgYaxsbZx1v9vlotZYxJWciIrXupm301Pb5wujKtM9ya9mxMdbeYO33WuDq+PjKBiQiK+p2k7MnrLUPAj8C/EtjzFMzn2Ct/Ya1dp+1dl9rZ+ttvt38hQgQT4VW7P1qzYauLtw5thXI5POM+f10aM2ZiEitu2kbPbV9Xt+6cu2z3NyGzk7cfH7WcWstnwAb2tpWPigRWTG3lZxZa8+U/jwPfBt4ZCmCul2pdAqyWa/DqGqP7djB309McGnKCNl4ocBfXrnCQ3ffrYqNIiI1rlrbaLm5BzZv5qPmZj6aMppprcUZGaFlwwZ6Ojo8jE5EltuiC4IYY9oAn7X2Sun254F/t2SRLVKiLwEjI7gvboNYzOtwqtZda9bw5MMP841Uim1Xr9IMfGwMu+++m8/cdZfX4YmIyG2o1jZabq2tqYl/9PjjvPjGG3w/k2GtMQxYS9uGDfzDhx7CzFgrLiL15XaqNW4Evl36kvADL1hrv7MkUS1SwjlIKJtXYjZP+3p6uK+7m2OXLpEvFHg6FCIUCHgdloiI3L6qa6Nl/rZ2dvKLTz/Nx5cukR0f5+G2Nja3tysxE1kFFp2cWWtPAJ9awlgWzXEdUm5fKTHrUWK2AM1+P/du2OB1GCIisoSqqY2WxfEZw861a70OQ0RWWM2X0ldiJiIiIiIi9WApNqH2zLTE7PABiEW9DklERERERGRRanbkzHEdUscPEUlTTMy0ybSIiIiIiNSwmkzOyiNmkSE/Tv9+JWYiIiIiIlLzjLV25d7MmAvAJ/N46jpgaJnDWUn1dD71dC6g86lm9XQu4M353GGtXb/C7yk1aAHtM9TX/816Oheor/Opp3OB+jqfejoXqLL2eUWTs/kyxhy21u7zOo6lUk/nU0/nAjqfalZP5wL1dz6yetXTv+V6Oheor/Opp3OB+jqfejoXqL7zqclpjSIiIiIiIvVGyZmIiIiIiEgVqNbk7BteB7DE6ul86ulcQOdTzerpXKD+zkdWr3r6t1xP5wL1dT71dC5QX+dTT+cCVXY+VbnmTEREREREZLWp1pEzERERERGRVaXqkjNjjGuMec8YkzLGHPY6noUyxvyuMea8MebIlGNrjDHfNcYcK/3Z5WWM83WDc4kbY06XPp+UMeZHvYxxvowxW40x3zPGfGiMed8Y84ul47X62dzofGr18wkYY35gjHmndD5fLx2vuc/nJudSk5+NSJna5+pRT+0z1Fcbrfa5etVK+1x10xqNMS6wz1pbk/snGGOeArLA71lr7y0d+7+AS9bag8aY54Eua+2/8TLO+bjBucSBrLX2V7yMbaGMMZuATdbat4wx7cCbwE8BMWrzs7nR+XyZ2vx8DNBmrc0aYxqBQ8AvAv+AGvt8bnIuz1CDn41Imdrn6lFP7TPUVxut9rl61Ur7XHUjZ7XOWvsycGnG4Z8Evlm6/U2K/0mr3g3OpSZZa89aa98q3b4CfAhsoXY/mxudT02yRdnS3cbSj6UGP5+bnIuIeEjtc/WqpzZa7XP1qpX2uRqTMwv8rTHmTWPMc14Hs0Q2WmvPQvE/LbDB43hu1y8YY94tTauo+mHsmYwxYeAB4HXq4LOZcT5Qo5+PMabBGJMCzgPftdbW7Odzg3OBGv1sRErUPle/mv+Oqac2Wu1z9amF9rkak7MnrLUPAj8C/MvS0L1Uj98E7gIiwFngVz2NZoGMMUHgj4Fea+2I1/HcrjnOp2Y/H2vtpLU2AvQAjxhj7vU4pEW7wbnU7GcjUqL2ubrV/HdMPbXRap+rUy20z1WXnFlrz5T+PA98G3jE24iWxLnSHOTyXOTzHsezaNbac6V/2AXgt6mhz6c0v/iPgT+01v5J6XDNfjZznU8tfz5l1toM4FCcA16znw9MP5d6+GxkdVP7XN1q/Tumntpotc/Vr5rb56pKzowxbaXFkxhj2oDPA0du/ls14c+Br5Vufw34Mw9juS3l/4glP02NfD6lRaC/A3xorf21KQ/V5Gdzo/Op4c9nvTEmVLrdAnwO6KcGP58bnUutfjYioPa5FtTyd0w9tdFqn6tXrbTPVVWt0RiznWJvHIAfeMFa+x88DGnBjDF/BESBdcA54JeBPwW+BWwDBoAvWWurfiHvDc4lSnHY1wIu8PPlOcfVzBhzAPg+8B5QKB3+JYrzwGvxs7nR+XyF2vx87qe4oLiBYqfRt6y1/84Ys5Ya+3xuci6/Tw1+NiKg9rna1FP7DPXVRqt9rl610j5XVXImIiIiIiKyWlXVtEYREREREZHVSsmZiIiIiIhIFVByJiIiIiIiUgWUnImIiIiIiFQBJWciIiIiIiJVQMmZiIiIiIhIFVByJiIiIiIiUgWUnImIiIiIiFSB/z9/+Usd5OG7qgAAAABJRU5ErkJggg==\n",
      "text/plain": [
       "<Figure size 1080x360 with 2 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "titles = ('K Neighbors with k=1',\n",
    "          'K Neighbors with k=2')\n",
    "\n",
    "fig = plt.figure(figsize=(15, 5))\n",
    "plt.subplots_adjust(wspace=0.4, hspace=0.4)\n",
    "\n",
    "X0, X1 = X_train[:, 0], X_train[:, 1]\n",
    "\n",
    "x_min, x_max = X0.min() - 1, X0.max() + 1\n",
    "y_min, y_max = X1.min() - 1, X1.max() + 1\n",
    "xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.2),\n",
    "                         np.arange(y_min, y_max, 0.2))\n",
    "\n",
    "for clf, title, ax in zip(models, titles, fig.subplots(1, 2).flatten()):    \n",
    "    Z = clf.predict(np.c_[xx.ravel(), yy.ravel()])\n",
    "    Z = Z.reshape(xx.shape) \n",
    "    colors = ('red', 'green', 'lightgreen', 'gray', 'cyan')  \n",
    "    cmap = ListedColormap(colors[:len(np.unique(Z))])  \n",
    "    ax.contourf(xx, yy, Z, cmap=cmap, alpha=0.5)\n",
    "    \n",
    "    ax.scatter(X0, X1, c=y_train, s=50, edgecolors='k', cmap=cmap, alpha=0.5)\n",
    "    ax.set_title(title)\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 习题3.2\n",
    "&emsp;&emsp;利用例题3.2构造的$kd$树求点$x=(3,4.5)^T$的最近邻点。\n",
    "\n",
    "**解答：**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "x点的最近邻点是(2, 3)\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "from sklearn.neighbors import KDTree\n",
    "\n",
    "train_data = np.array([(2, 3), (5, 4), (9, 6), (4, 7), (8, 1), (7, 2)])\n",
    "tree = KDTree(train_data, leaf_size=2)\n",
    "dist, ind = tree.query(np.array([(3, 4.5)]), k=1)\n",
    "x1 = train_data[ind[0]][0][0]\n",
    "x2 = train_data[ind[0]][0][1]\n",
    "\n",
    "print(\"x点的最近邻点是({0}, {1})\".format(x1, x2))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 习题3.3\n",
    "&emsp;&emsp;参照算法3.3，写出输出为$x$的$k$近邻的算法。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**解答：**  \n",
    "**算法：用kd树的$k$近邻搜索**  \n",
    "输入：已构造的kd树；目标点$x$；    \n",
    "输出：$x$的最近邻    \n",
    "1. 在$kd$树中找出包含目标点$x$的叶结点：从根结点出发，递归地向下访问树。若目标点$x$当前维的坐标小于切分点的坐标，则移动到左子结点，否则移动到右子结点，直到子结点为叶结点为止；  \n",
    "2. 如果“当前$k$近邻点集”元素数量小于$k$或者叶节点距离小于“当前$k$近邻点集”中最远点距离，那么将叶节点插入“当前k近邻点集”；  \n",
    "3. 递归地向上回退，在每个结点进行以下操作：  \n",
    "(a)如果“当前$k$近邻点集”元素数量小于$k$或者当前节点距离小于“当前$k$近邻点集”中最远点距离，那么将该节点插入“当前$k$近邻点集”。  \n",
    "(b)检查另一子结点对应的区域是否与以目标点为球心、以目标点与于“当前$k$近邻点集”中最远点间的距离为半径的超球体相交。如果相交，可能在另一个子结点对应的区域内存在距目标点更近的点，移动到另一个子结点，接着，递归地进行最近邻搜索；如果不相交，向上回退；\n",
    "4. 当回退到根结点时，搜索结束，最后的“当前$k$近邻点集”即为$x$的最近邻点。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 构建kd树，搜索待预测点所属区域\n",
    "from collections import namedtuple\n",
    "import numpy as np\n",
    "\n",
    "\n",
    "# 建立节点类\n",
    "class Node(namedtuple(\"Node\", \"location left_child right_child\")):\n",
    "    def __repr__(self):\n",
    "        return str(tuple(self))\n",
    "\n",
    "\n",
    "# kd tree类\n",
    "class KdTree():\n",
    "    def __init__(self, k=1):\n",
    "        self.k = k\n",
    "        self.kdtree = None\n",
    "\n",
    "    # 构建kd tree\n",
    "    def _fit(self, X, depth=0):\n",
    "        try:\n",
    "            k = self.k\n",
    "        except IndexError as e:\n",
    "            return None\n",
    "        # 这里可以展开，通过方差选择axis\n",
    "        axis = depth % k\n",
    "        X = X[X[:, axis].argsort()]\n",
    "        median = X.shape[0] // 2\n",
    "        try:\n",
    "            X[median]\n",
    "        except IndexError:\n",
    "            return None\n",
    "        return Node(\n",
    "            location=X[median],\n",
    "            left_child=self._fit(X[:median], depth + 1),\n",
    "            right_child=self._fit(X[median + 1:], depth + 1)\n",
    "        )\n",
    "\n",
    "    def _search(self, point, tree=None, depth=0, best=None):\n",
    "        if tree is None:\n",
    "            return best\n",
    "        k = self.k\n",
    "        # 更新 branch\n",
    "        if point[0][depth % k] < tree.location[depth % k]:\n",
    "            next_branch = tree.left_child\n",
    "        else:\n",
    "            next_branch = tree.right_child\n",
    "        if not next_branch is None:\n",
    "            best = next_branch.location\n",
    "        return self._search(point, tree=next_branch, depth=depth + 1, best=best)\n",
    "\n",
    "    def fit(self, X):\n",
    "        self.kdtree = self._fit(X)\n",
    "        return self.kdtree\n",
    "\n",
    "    def predict(self, X):\n",
    "        res = self._search(X, self.kdtree)\n",
    "        return res "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "x点的最近邻点是(2, 3)\n"
     ]
    }
   ],
   "source": [
    "KNN = KdTree()\n",
    "X_train = np.array([[2, 3],\n",
    "                    [5, 4],\n",
    "                    [9, 6],\n",
    "                    [4, 7],\n",
    "                    [8, 1],\n",
    "                    [7, 2]])\n",
    "KNN.fit(X_train)\n",
    "X_new = np.array([[3, 4.5]])\n",
    "res = KNN.predict(X_new)\n",
    "\n",
    "x1 = res[0]\n",
    "x2 = res[1]\n",
    "\n",
    "print(\"x点的最近邻点是({0}, {1})\".format(x1, x2))"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.1"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
